from ast import main
import re
import requests
import hashlib
import time
import json
import urllib.parse
import logging
from typing import Dict, Any, Optional, List, Union


# 向吉客云开放平台发送API请求
def send_api_request(app_key: str, app_secret: str, method: str, bizdata: str) -> Dict[str, Any]:
    """
    :param app_key: 应用的AppKey
    :param app_secret: 应用的AppSecret
    :param method: API接口名称
    :param bizdata: 业务请求参数（JSON格式字符串）
    """
    api_url = "https://open.jackyun.com/open/openapi/do"
    # 准备用于签名的参数
    params_for_sign = {
        'method': method,
        'appkey': app_key,
        'version': '1.0',
        'contenttype': 'json',
        'timestamp': time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
        'bizcontent': bizdata
    }
    # 生成签名
    sorted_params = sorted(params_for_sign.items())
    query_string = ""
    for key, value in sorted_params:
        if key and value:
            query_string += f"{key}{value}"
    sign_string = (app_secret + query_string + app_secret).lower()
    signature = hashlib.md5(sign_string.encode('utf-8')).hexdigest().lower()
    # 3. 准备最终请求体
    post_data_parts = []
    # 将签名加入到参数中
    params_for_sign['sign'] = signature
    for key, value in params_for_sign.items():
        if key == 'bizcontent':
            # 只对bizcontent进行URL编码
            post_data_parts.append(f"{key}={urllib.parse.quote(value)}")
        else:
            post_data_parts.append(f"{key}={value}")
    post_data_str = "&".join(post_data_parts)
    # 发送请求
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
    }
    try:
        response = requests.post(api_url, data=post_data_str.encode('utf-8'), headers=headers)
        response.raise_for_status()
        # 解析响应
        api_response = response.json()
        try:
            logging.info(f"吉客云API原始响应: {api_response}")
        except (IOError, OSError) as log_error:
            # 日志记录失败不影响API调用结果，静默处理
            pass
        # 直接返回吉客云的原始响应
        return api_response

    except requests.exceptions.Timeout:
        print("请求超时")
        return {
            'success': False,
            'code': 'TIMEOUT',
            'message': '请求超时，请稍后重试'
        }
    except requests.exceptions.ConnectionError:
        print("网络连接错误")
        return {
            'success': False,
            'code': 'CONNECTION_ERROR',
            'message': '网络连接失败，请检查网络设置'
        }
    except requests.exceptions.HTTPError as e:
        print(f"HTTP错误: {e}")
        return {
            'success': False,
            'code': f'HTTP_{e.response.status_code}',
            'message': f'HTTP错误: {e.response.status_code}'
        }
    except json.JSONDecodeError:
        print("响应不是有效的JSON格式")
        return {
            'success': False,
            'code': 'INVALID_JSON',
            'message': '服务器响应格式错误'
        }
    except requests.exceptions.RequestException as e:
        print(f"请求出错: {e}")
        return {
            'success': False,
            'code': 'REQUEST_ERROR',
            'message': f'请求失败: {str(e)}'
        }
    except Exception as e:
        logging.error(f"未知错误: {e}")
        return {
            'success': False,
            'code': 'UNKNOWN_ERROR',
            'message': f'未知错误: {str(e)}'
        }


def process_external_customer_data_md(external_data: Dict[str, Any]) -> Dict[str, Any]:
    """
    处理外部传入的客户数据，进行数据清洗和格式转换（门店版本）
    :param external_data: 外部传入的原始客户数据
    :return: 处理后的客户数据或错误信息
    """
    try:
        # 数据清洗和验证
        customer_code = str(external_data.get('customerCode', '')).strip()
        nickname = str(external_data.get('nickname', '')).strip()
        phone = str(external_data.get('phone', '')).strip()
        customer_source_arr_input = external_data.get('customerSourceArr', [])
        create_channel_info_input = external_data.get('createChannelInfo', {})
        customer_account = str(external_data.get('customerAccount', ''))
        tag_arr = str(external_data.get('tagArr', '')).strip()
        gender = external_data.get('gender')  # gender参数如果没有传入，默认为空(None)
        address = external_data.get('address', '')  # 获取地址信息

        # 必填字段验证
        if not customer_code:
            return {
                'success': False,
                'code': 'INVALID_PARAMS',
                'message': '客户编码不能为空'
            }

        if not phone:
            return {
                'success': False,
                'code': 'INVALID_PARAMS',
                'message': '客户手机号不能为空'
            }

        # 手机号格式验证
        import re
        if not re.match(r'^1[3-9]\d{9}$', phone):
            return {
                'success': False,
                'code': 'INVALID_PARAMS',
                'message': '手机号格式不正确'
            }

        # 如果nickname为空，使用customerCode作为默认昵称
        if not nickname:
            nickname = customer_code

        # 处理customerSourceArr - 支持字符串和数组格式
        # customerAccount需要在传入的customerCode前加ZH前缀
        if customer_account:
            customer_account = f"ZH{customer_account}"
        else:
            customer_account = f"ZH{customer_code}"

        if customer_source_arr_input:
            if isinstance(customer_source_arr_input, list):
                # 如果是数组格式，直接使用
                customer_source_arr = customer_source_arr_input
            elif isinstance(customer_source_arr_input, str):
                # 如果是字符串格式，转换为标准格式
                customer_source_arr = [{
                    "channelId": 1988543689976512896,
                    "sourceChannel": customer_source_arr_input.strip(),
                    "customerAccount": customer_account,
                    "isDefault": 1
                }]
            else:
                # 其他格式使用默认值
                customer_source_arr = [{
                    "channelId": 1988543689976512896,
                    "sourceChannel": "MD-吉商城",
                    "customerAccount": customer_account,
                    "isDefault": 1
                }]
        else:
            # 默认来源
            customer_source_arr = [{
                "channelId": 1988543689976512896,
                "sourceChannel": "MD-吉商城",
                "customerAccount": customer_account,
                "isDefault": 1
            }]

        # 设置默认VIP等级
        vip_level_name = "白银会员"
        vip_level = "2063198562018002432"

        # 处理创建渠道信息 - 支持自定义渠道
        if create_channel_info_input and isinstance(create_channel_info_input, dict):
            # 验证渠道信息格式
            if 'channelId' in create_channel_info_input and 'channelName' in create_channel_info_input:
                create_channel_info = create_channel_info_input
            else:
                # 格式不正确，使用默认值
                create_channel_info = {
                    "channelId": 1988543689976512896,
                    "channelName": "MD-吉商城"
                }
        else:
            # 默认渠道信息
            create_channel_info = {
                "channelId": 2073951852469027584,
                "channelName": "MD-吉商城"
            }

        # 处理标签数组，保持为数组格式
        if tag_arr:
            # 按空格分割标签
            tags = tag_arr.split()
            tag_names = []
            for tag in tags:
                if tag.strip():
                    tag_names.append(tag.strip())
            tag_arr_result = tag_names
        else:
            tag_arr_result = []

        # 处理地址信息
        state = ""
        city = ""
        district = ""
        town = ""
        detailed_address = ""

        # 如果address是字符串，处理它
        if address:
            try:
                if isinstance(address, str):
                    # 首先尝试用分隔符分割地址字符串
                    address_parts = [part.strip() for part in re.split(r'[\s,，:：]+', address) if part]
                    # 如果分割后部分少于3个，尝试用地名模式分割
                    if len(address_parts) < 3:
                        # 尝试识别省市区的模式：省/市/自治区 + 市/州/盟 + 区/县/市
                        pattern = r'([^市区县]+[市]?)([^区县市]+[区县市]?)(.*)'
                        match = re.match(pattern, address)
                        if match:
                            state_part = match.group(1)
                            city_district_part = match.group(2)
                            remaining_part = match.group(3)

                            # 处理剩余部分（去掉开头的冒号）
                            if remaining_part.startswith(':') or remaining_part.startswith('：'):
                                remaining_part = remaining_part[1:].strip()

                            address_parts = [state_part, city_district_part, remaining_part] if remaining_part else [
                                state_part, city_district_part]

                    if len(address_parts) >= 3:
                        # 格式：省,市,区[,镇][,详细地址] 或 省,市,详细地址
                        state = address_parts[0]
                        city = address_parts[1]

                        if len(address_parts) == 3:
                            # 3个部分：省,市,区或详细地址
                            # 判断第3部分是否为区级单位（通常以"区"、"县"、"市"结尾）
                            third_part = address_parts[2]
                            if third_part.endswith(('区', '县', '市')):
                                district = third_part
                                detailed_address = ""  # 没有详细地址
                            else:
                                # 第3部分不是区级单位，可能是详细地址
                                district = ""
                                detailed_address = third_part
                        elif len(address_parts) == 4:
                            # 4个部分：需要判断第4部分是否为有效的详细地址
                            third_part = address_parts[2]
                            fourth_part = address_parts[3]

                            # 判断第3部分是否为区级单位
                            if third_part.endswith(('区', '县', '市')):
                                district = third_part
                                # 判断第4部分是否为有效的详细地址或镇级单位
                                if fourth_part.endswith(('镇', '街道', '乡', '村')) or len(fourth_part) > 2:
                                    if fourth_part.endswith(('镇', '街道', '乡')):
                                        town = fourth_part
                                        detailed_address = ""
                                    else:
                                        detailed_address = fourth_part
                                else:
                                    # 第4部分太短或无效，忽略它
                                    detailed_address = ""
                            else:
                                # 第3部分不是区级单位，将第3、4部分合并为详细地址
                                district = ""
                                detailed_address = f"{third_part} {fourth_part}"
                        elif len(address_parts) >= 5:
                            # 5个或更多部分：省,市,区,镇,详细地址...
                            district = address_parts[2]
                            town = address_parts[3]
                            detailed_address = ' '.join(address_parts[4:])
                    else:
                        # 如果少于3个部分，将整个地址作为详细地址
                        detailed_address = address
                        logging.warning(f"地址格式不符合预期的省市区格式，已将整个地址存入详细地址: {address}")
            except Exception as e:
                logging.warning(f"解析地址信息失败: {str(e)}")

        # 返回处理后的数据
        processed_data = {
            'customerCode': f"MD{customer_code}",  # customerCode需要添加MD前缀
            'nickname': nickname,
            'phone': phone,
            'vipLevelName': vip_level_name,
            'vipLevel': vip_level,
            'customerSourceArr': customer_source_arr,
            'createChannelInfo': create_channel_info,
            'tagArr': tag_arr_result
        }

        # 添加地址信息到处理后的数据
        if state:
            processed_data['state'] = state

        if city:
            processed_data['city'] = city

        if district:
            processed_data['district'] = district

        if town:
            processed_data['town'] = town

        if detailed_address:
            processed_data['detailedAddress'] = detailed_address

        # 只有当gender不为None时才添加gender字段
        if gender is not None:
            processed_data['gender'] = gender
        return {
            'success': True,
            'data': processed_data
        }
    except Exception as e:
        return {
            'success': False,
            'code': 'DATA_PROCESS_ERROR',
            'message': f'数据处理失败: {str(e)}'
        }


def create_customer_from_external_data_md(external_data: Dict[str, Any]) -> Dict[str, Any]:
    """
    根据外部传入的数据创建客户档案（门店版本）
    :param external_data: 外部传入的原始客户数据
    :return: 创建结果
    """
    # 先进行数据处理
    process_result = process_external_customer_data_md(external_data)

    if not process_result.get('success'):
        return process_result

    # 获取处理后的数据
    processed_data = process_result['data']

    # 调用AddCustomerMD函数创建客户
    return AddCustomerMD(
        customerCode=processed_data['customerCode'],
        nickname=processed_data['nickname'],
        phone=processed_data['phone'],
        vipLevelName=processed_data['vipLevelName'],
        vipLevel=processed_data['vipLevel'],
        customerSourceArr=processed_data['customerSourceArr'],
        createChannelInfo=processed_data['createChannelInfo'],
        tagArr=processed_data['tagArr'],
        gender=processed_data.get('gender'),  # 传递gender参数，如果不存在则为None
        state=processed_data.get('state'),  # 传递state参数
        city=processed_data.get('city'),  # 传递city参数
        district=processed_data.get('district'),  # 传递district参数
        town=processed_data.get('town'),  # 传递town参数
        detailedAddress=processed_data.get('detailedAddress')  # 传递detailedAddress参数
    )


def AddCustomerMD(customerCode: str, nickname: str, phone: str, vipLevelName: str,
                  vipLevel: str, customerSourceArr: List[Dict[str, Any]],
                  createChannelInfo: Dict[str, Any], tagArr: List[str] = None,
                  gender: Optional[int] = None, state: Optional[str] = None,
                  city: Optional[str] = None, district: Optional[str] = None,
                  town: Optional[str] = None, detailedAddress: Optional[str] = None) -> Dict[str, Any]:
    """
    添加客户到吉客云系统（门店版本）
    :param customerCode: 客户编码 (必填)
    :param nickname: 客户名称 (必填)
    :param phone: 客户手机号 (必填)
    :param vipLevelName: 客户vip等级名称 (必填)
    :param vipLevel: 客户vip等级ID (必填)
    :param customerSourceArr: 客户来源数组 (必填)
    :param createChannelInfo: 创建渠道信息 (必填)
    :param tagArr: 客户标签数组 (可选，默认为空数组)
    :param gender: 客户性别 (可选，1-男，2-女，如果没有传入则默认为空)
    :param state: 省份 (可选)
    :param city: 城市 (可选)
    :param district: 区 (可选)
    :param town: 镇 (可选)
    :param detailedAddress: 详细地址 (可选)
    :return: API响应结果
    """

    # 参数验证
    if not customerCode or not nickname or not phone or not vipLevelName or not vipLevel:
        return {
            'success': False,
            'code': 'INVALID_PARAMS',
            'message': '客户编码、客户名称、手机号、VIP等级名称和VIP等级ID为必填参数'
        }

    if not customerSourceArr or not createChannelInfo:
        return {
            'success': False,
            'code': 'INVALID_PARAMS',
            'message': '客户来源数组和创建渠道信息为必填参数'
        }
    if tagArr is None:
        tagArr = []

    # 构造请求参数 
    data = {
        "customerCode": customerCode,  # 已经在process_external_customer_data_md中添加了MD前缀
        "nickname": nickname,
        "phone": phone,
        "vipLevelName": vipLevelName,
        "vipLevel": vipLevel,
        "customerSourceArr": customerSourceArr,
        "createChannelInfo": createChannelInfo,
        "tagArr": tagArr
    }

    # 只有当gender不为None时才添加gender字段
    if gender is not None:
        data["gender"] = gender

    # 添加地址信息（只有非空字符串才添加）
    if state and state.strip():
        data["state"] = state

    if city and city.strip():
        data["city"] = city

    if district and district.strip():
        data["district"] = district

    if town and town.strip():
        data["town"] = town

    if detailedAddress and detailedAddress.strip():
        data["detailedAddress"] = detailedAddress
    # API配置
    APP_KEY = "12540443"
    APP_SECRET = "a7860451c1b6470da900bd40d91addb2"
    METHOD = "crm.customer.add"

    # 将数据转换为JSON字符串
    bizdata = json.dumps(data, ensure_ascii=False)

    try:
        # 调用统一的API请求函数
        response = send_api_request(APP_KEY, APP_SECRET, METHOD, bizdata)

        # 记录请求日志
        try:
            logging.info(f"添加门店客户请求 - 客户编码: {customerCode}, 客户名称: {nickname}")
            logging.info(f"API响应: {response}")
        except (IOError, OSError):
            # 日志记录失败不影响API调用结果，静默处理
            pass

        # 处理吉客云API响应格式 - 简化版本
        if isinstance(response, dict):
            # 检查吉客云标准响应格式
            if 'code' in response and response['code'] == 200:
                # 吉客云成功响应
                result_data = response.get('result', {})
                return {
                    'success': True,
                    'message': '门店客户创建成功',
                    'data': {
                        'customer_id': result_data.get('data'),
                        'context_id': result_data.get('contextId'),
                        'customer_code': customerCode
                    }
                }
            elif 'code' in response and response['code'] != 200:
                # 吉客云错误响应
                return {
                    'success': False,
                    'message': response.get('msg', '门店客户创建失败'),
                    'error_code': response['code']
                }
            elif response.get('success') is False:
                # 我们自己的错误响应格式
                return {
                    'success': False,
                    'message': response.get('message', '门店客户创建失败')
                }
            else:
                # 其他格式，默认成功
                return {
                    'success': True,
                    'message': '门店客户创建成功',
                    'data': {
                        'customer_id': response.get('data') if isinstance(response, dict) else None,
                        'context_id': response.get('contextId') if isinstance(response, dict) else None,
                        'customer_code': customerCode
                    }
                }
        else:
            # 非字典响应
            return {
                'success': False,
                'message': '服务器响应格式异常'
            }

    except Exception as e:
        error_msg = f"添加门店客户时发生错误: {str(e)}"
        try:
            logging.error(error_msg)
        except (IOError, OSError):
            # 日志记录失败不影响API调用结果，静默处理
            pass

        return {
            'success': False,
            'code': 'FUNCTION_ERROR',
            'message': error_msg
        }
